package com.ht.oauthserver.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;

/**
 * oauth2 * oath2有四种方式获取token
 *
 * @Description
 *              <p>
 *              1. authorization_code
 *              {@link http://host:port/oauth/authorize?client_id={cliendid}&response_type=code&redirect_uri={返回地址}}
 *              <p>
 *              服务器验证通过后,返会code,用户拿到code 后
 *              请求{@link http://host:port/oauth/token} - post
 *              grant_type=authorization_code&code={上一步拿到的code}&client_id={clientid}&redirect_uri={请求code的时候的返回地址}
 *              </p>
 *              <p>
 *              服务器拿到 token
 *              </p>
 *
 *              </p>
 *              <p>
 *              2.password {@link http://host:port/oauth/token} -post
 *              username={username}&password={password}&grant_type=password&client_id={client_id}&client_secret={client_secret}
 *              </p>
 *              <p>
 *              3.client_credentials {@link http://host:port/oauth/token} -post
 *              grant_type=client_credentials&client_id={client_id}&client_secret={client_secret}
 *              </p>
 *              <p>
 *              4.刷新token请求 refresh_token {@link http://host:port/oauth/token}
 *              -post
 *              grant_type=refresh_token&refresh_token={token}&client_id={client_id}&client_secret={client_secret}
 *              </p>
 *              <p>
 *              4.检查头肯是否有效请求
 *              {@link http://host:port/oauth/check_token?token=token }
 *              </p>
 *
 * @author czy
 * @CreateDate 2020-05-21 09:53:04
 * @UpdateDate 2020-05-21 09:53:04
 *
 */
@Configuration
@EnableAuthorizationServer
public class Oauth2ServerConfig extends AuthorizationServerConfigurerAdapter {
    private TokenStore tokenStore = new InMemoryTokenStore();

    @Autowired
    private AuthenticationManager authenticationManager;

    /**
     * 用来配置授权（authorization）以及令牌（token）的访问端点和令牌服务(token services)。
     *
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenServices(tokenServices()).authenticationManager(this.authenticationManager);

    }

    /**
     *
     * 配置客户端,用户,验证方式
     *
     * @Description 配置客户端详情信息（Client Details)：
     *
     * @CreateDate 2020-05-21 10:20:40
     * @UpdateDate 2020-05-21 10:20:40
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory().withClient("test").secret(new PasswordEncoder() {

            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {

                return true;
            }

            @Override
            public String encode(CharSequence rawPassword) {
                return rawPassword.toString();
            }
        }.encode("test")).scopes("all").authorities("all").accessTokenValiditySeconds(10000)
                .refreshTokenValiditySeconds(10000)
                .authorizedGrantTypes("client_credentials", "refresh_token", "authorization_code", "password")
                .redirectUris("http://localhost:8081/oauth/client_redirct");

        // super.configure(clients);

    }

    /**
     * 用来配置令牌端点(Token Endpoint)的安全约束.
     *
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()") // allow check token
                .allowFormAuthenticationForClients();
        super.configure(security);
    }

    @Bean
    @Primary
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setSupportRefreshToken(true);
        tokenServices.setTokenStore(this.tokenStore);
        return tokenServices;
    }
}